package com.sojson.util.qq;

import com.alibaba.fastjson.JSONObject;
import com.sojson.config.exception.TransErrorCode;
import com.sojson.constant.Constant;
import com.sojson.enums.core.ESex;
import com.sojson.result.bean.Status;
import com.sojson.util.OtherUtil;
import com.sojson.util.StringUtil;
import com.sojson.util.bean.OtherUser;
import com.sojson.util.httpclient.HttpClientUtil;
import com.sojson.util.json.JsonUtil;

/**
 * QQ工具类
 * 
 * @author liu
 * @date 2020-09-09
 */
public class QqUtil {

    /** ----------------------------以下是静态属性---------------------------- */
    /** ----------------------------以下是静态属性---------------------------- */
    /** ----------------------------以下是静态属性---------------------------- */

    /** ----------------------------以下是QQ用户帐号---------------------------- */
    /** ----------------------------以下是QQ用户帐号---------------------------- */
    /** ----------------------------以下是QQ用户帐号---------------------------- */
    /** 类似帐号 */
    public static final String APPID = Constant.PROPERTIES.getProperty("so.qq.appid");
    /** 类似密码 */
    public static final String APPSECRET = Constant.PROPERTIES.getProperty("so.qq.appsecret");

    /** ----------------------------以下是QQ接口返回的参数---------------------------- */
    /** ----------------------------以下是QQ接口返回的参数---------------------------- */
    /** ----------------------------以下是QQ接口返回的参数---------------------------- */
    // =======================================================================================================
    // =================================================用户信息================================================
    // =======================================================================================================
    /** 参数: openid(用户的唯一标识) */
    public static final String FIELD_OPENID = "openid";
    /** 参数: unionid(用户的唯一标识,多平台的唯一标识(WEB,移动...)) */
    public static final String FIELD_UNIONID = "unionid";
    /** 参数: nickname(昵称) */
    public static final String FIELD_NICKNAME = "nickname";
    /** 参数: figureurl_qq_1(头像) */
    public static final String FIELD_FIGUREURL = "figureurl_qq_1";
    /** 参数: gender(性别) */
    public static final String FIELD_GENDER = "gender";
    // =======================================================================================================
    // =======================================================================================================
    // =======================================================================================================
    /** 参数: access_token(用户授权的唯一票据,用于调用QQ的开放接口) */
    public static final String FIELD_ACCESS_TOKEN = "access_token";
    /** 参数: client_id(申请应用时分配的appid) */
    public static final String FIELD_CLIENT_ID = "client_id";
    // =======================================================================================================
    // =================================================状态码=================================================
    // =======================================================================================================
    /** 参数: error */
    public static final String FIELD_ERROR = "error";
    /** 参数: error_description */
    public static final String FIELD_ERROR_MESSAGE = "error_description";
    /** 参数: ret */
    public static final String FIELD_RET = "ret";
    /** 参数: msg */
    public static final String FIELD_MSG = "msg";

    /** ----------------------------以下是QQ访问地址---------------------------- */
    /** ----------------------------以下是QQ访问地址---------------------------- */
    /** ----------------------------以下是QQ访问地址---------------------------- */
    /** QQWEB端获取认证CODE的路径 */
    public static final String WEB_CODE_URL =
        StringUtil.isNotBlank(Constant.PROPERTIES.getProperty("so.qq.web.codeUrl"))
            ? String.format(Constant.PROPERTIES.getProperty("so.qq.web.codeUrl"), APPID, "%s", "%s") : "";
    /** QQ移动端获取认证CODE的路径 */
    public static final String MOBILE_CODE_URL =
        StringUtil.isNotBlank(Constant.PROPERTIES.getProperty("so.qq.mobile.codeUrl"))
            ? String.format(Constant.PROPERTIES.getProperty("so.qq.mobile.codeUrl"), APPID, "%s", "%s") : "";
    /** 获取用户认证AccessToken的路径 */
    public static final String USER_ACCESS_TOKEN_URL =
        StringUtil.isNotBlank(Constant.PROPERTIES.getProperty("so.qq.userAccessTokenUrl"))
            ? String.format(Constant.PROPERTIES.getProperty("so.qq.userAccessTokenUrl"), APPID, APPSECRET, "%s", "%s")
            : "";
    /** 获取QQ用户openid的路径 */
    public static final String USER_OPENID = Constant.PROPERTIES.getProperty("so.qq.openidUrl");
    /** 获取QQ用户信息的路径 */
    public static final String USER_INFO_URL = Constant.PROPERTIES.getProperty("so.qq.userInfoUrl");

    /**
     * 获取QQ用户认证AccessToken
     * 
     * @param code
     * @return
     * @throws Exception
     */
    public static QqBean getUserAccessToken(String code) throws Exception {
        String urlResult =
            HttpClientUtil.doGet(String.format(USER_ACCESS_TOKEN_URL, code, OtherUtil.ENCODE_AUTHC_CODE_CALL_BACK));
        if (StringUtil.isBlankObject(urlResult)) {
            return new QqBean(TransErrorCode.OTHER_ERROR.getCode(), "通过CODE获取QQ用户认证AccessToken,路径没有返回任何值!");
        }

        JSONObject jsonObject = JsonUtil.jsonToObject(urlResult, JSONObject.class);
        Integer errorCode = jsonObject.getInteger(FIELD_ERROR);
        if (StringUtil.isNotBlankObject(errorCode)) {
            return new QqBean(errorCode, jsonObject.getString(FIELD_ERROR_MESSAGE));
        }

        QqBean qqBean = new QqBean(TransErrorCode.SUCCESS.getCode());
        qqBean.setAccessToken(jsonObject.getString(FIELD_ACCESS_TOKEN));
        return qqBean;
    }

    /**
     * 获取QQ用户的openid
     * 
     * @param code QQ用户登录QQ平台后,QQ平台返回给回调接口的code
     * @return
     * @throws Exception
     */
    public static QqBean getUserOpenid(String code) throws Exception {
        QqBean authorization = getUserAccessToken(code);

        Status status = authorization.getStatus();
        if (status.getCode() == TransErrorCode.SUCCESS.getCode()) {
            return getUserOpenid(authorization);
        }
        return authorization;
    }

    /**
     * 获取QQ用户的openid
     * 
     * @param qqBean 通过QqUtils.getUserAccessToken(String code)查出来的QqBean
     * @return
     * @throws Exception
     */
    public static QqBean getUserOpenid(QqBean qqBean) throws Exception {
        String urlResult = HttpClientUtil.doGet(String.format(USER_OPENID, qqBean.getAccessToken()));
        if (StringUtil.isBlankObject(urlResult)) {
            return new QqBean(TransErrorCode.OTHER_ERROR.getCode(), "通过WEB端QQ用户认证AccessToken获取用户openid,路径没有返回任何值!");
        }

        JSONObject jsonObject = JsonUtil.jsonToObject(urlResult, JSONObject.class);
        Integer errorCode = jsonObject.getInteger(FIELD_ERROR);
        if (StringUtil.isNotBlankObject(errorCode)) {
            return new QqBean(errorCode, jsonObject.getString(FIELD_ERROR_MESSAGE));
        }

        qqBean.setAppId(jsonObject.getString(FIELD_CLIENT_ID));
        qqBean.setOpenid(jsonObject.getString(FIELD_OPENID));
        qqBean.setUnionid(jsonObject.getString(FIELD_UNIONID));
        return qqBean;
    }

    /**
     * 获取QQ用户的信息
     * 
     * @param code QQ用户登录QQ平台后,QQ平台返回给回调接口的code
     * @return
     * @throws Exception
     */
    public static OtherUser getUserMessage(String code) throws Exception {
        QqBean authorization = getUserOpenid(code);

        Status status = authorization.getStatus();
        if (status.getCode() == TransErrorCode.SUCCESS.getCode()) {
            return getUserMessageByOpenid(authorization);
        }
        return new OtherUser(authorization.getStatus());
    }

    /**
     * 获取QQ用户的信息
     * 
     * @param qqBean 通过QqUtils.getUserAccessToken(?)查出来的QqBean
     * @return
     * @throws Exception
     */
    public static OtherUser getUserMessageByAccessToken(QqBean qqBean) throws Exception {
        QqBean authorization = getUserOpenid(qqBean);

        Status status = authorization.getStatus();
        if (status.getCode() == TransErrorCode.SUCCESS.getCode()) {
            return getUserMessageByOpenid(authorization);
        }
        return new OtherUser(authorization.getStatus());
    }

    /**
     * 获取QQ用户的信息
     * 
     * @param qqBean 通过QqUtils.getUserOpenid(?)查出来的QqBean
     * @return
     * @throws Exception
     */
    public static OtherUser getUserMessageByOpenid(QqBean qqBean) throws Exception {
        String urlResult = HttpClientUtil
            .doGet(String.format(USER_INFO_URL, qqBean.getAccessToken(), qqBean.getAppId(), qqBean.getOpenid()));
        if (StringUtil.isBlankObject(urlResult)) {
            return new OtherUser(TransErrorCode.OTHER_ERROR.getCode(), "通过WEB端QQ用户认证获取用户信息,路径没有返回任何值!");
        }

        JSONObject jsonObject = JsonUtil.jsonToObject(urlResult, JSONObject.class);
        Integer errorCode = jsonObject.getInteger(FIELD_RET);
        if (StringUtil.isNotBlankObject(errorCode) && errorCode != 0) {
            return new OtherUser(errorCode, jsonObject.getString(FIELD_MSG));
        }

        OtherUser user = new OtherUser(TransErrorCode.SUCCESS.getCode());
        user.setAppId(qqBean.getUnionid());
        user.setNickname(jsonObject.getString(FIELD_NICKNAME));
        String figureurl = jsonObject.getString(FIELD_FIGUREURL);
        if (ESex.UNKNOWN.getName().equals(figureurl)) {
            user.setSex(ESex.UNKNOWN.getCode());
        } else if (ESex.MAN.getName().equals(figureurl)) {
            user.setSex(ESex.MAN.getCode());
        } else if (ESex.GIRL.getName().equals(figureurl)) {
            user.setSex(ESex.GIRL.getCode());
        }
        user.setHeadImg(jsonObject.getString(FIELD_FIGUREURL));
        return user;
    }

}